package embuzzled.g5;

import java.awt.Color;
import java.util.ArrayList;
import java.util.Random;

/**
 *  A puzzle composed of multiple elements.
 *  For instance, a word containing multiple letters,
 *  or a series containing multiple elements.
 *
 */

public class CompositePuzzle implements Puzzle
{
	// Contains each of the components of this composite
	ArrayList<PuzzleComponent> components;
	
	//Stores the solution to this puzzle
	String solution;
	
	//Stores how this puzzle should be placed on the grid
	int[] placementStrategies;
	
	//Stores how this puzzle should be colored
	int coloringStrategy;
	
	public CompositePuzzle()
	{
		components = new ArrayList<PuzzleComponent>();
	}
	
	/**
	 * Returns a list of all components in this composite puzzle,
	 * in the order they were added.
	 */
	public ArrayList<PuzzleComponent> getComponents()
	{
		return components;
	}
	
	/**
	 *  Empty method to ensure compatibility with Puzzle interface.
	 *  Puzzle adding method will use this method for standalone
	 *  puzzles, and getComponents() for composite puzzles.
	 * @return null
	 */
	public Color[][] returnLocalColorMap()
	{
		return null;
	}
	
	/**
	 *  Adds a new component to this puzzle.
	 *  This always adds, because components are discrete,
	 *  and not overlapping.
	 * @param p A puzzle component.
	 */
	public void add(PuzzleComponent p)
	{
		components.add(p);
	}
	
	/**
	 *  Estimated minimum width, assuming all components are laid
	 *  in a horizontal line with no spacing.
	 * @return The total width of each component in this puzzle.
	 */
	public int getWidth()
	{
		int w = 0;
		
		for(PuzzleComponent p : components)
			w += p.getWidth();
		
		return 0;
	}
	
	/**
	 *  Estimated minimum width, assuming all components are laid
	 *  in a vertical line with no spacing.
	 * @return The total height of each component in this puzzle.
	 */
	public int getHeight()
	{
		int h = 0;
		
		for(PuzzleComponent p : components)
			h += p.getHeight();
		return 0;
	}
	
	/**
	 * Always returns true.
	 * Used by a placement method to determine what type of puzzle
	 * this is.
	 */
	public boolean isComposite()
	{
		return true;
	}
	
	/**
	 *  Sets the ways a placement method can add this puzzle
	 *  to the grid.
	 *  Strats should use the placement constants as defined
	 *  in the Constants class.
	 * @param strats A list of placement strategies.
	 */
	public void setPlacementStrategies(int[] strats)
	{
		placementStrategies = strats;
	}
	
	/**
	 *  Returns the list of ways this puzzle can be placed.
	 */
	public int[] getPlacementStrategies()
	{
		return placementStrategies;
	}
	
	/**
	 * Returns a String detailing the solution to this puzzle.
	 */
	public String getSolution()
	{
		return solution;
	}

	/**
	 * Sets the color for each component in this puzzle based on 
	 * the previously set coloring scheme.
	 * @param possibleColors A list of what colors it is possible to color this puzzle.
	 */
	public void setColor(Color[] possibleColors) 
	{
		System.out.println("Coloring...");
		Random r = new Random();
		Color c;
		
		switch(coloringStrategy)
		{
		case Constants.COLORING_MONOCOLOR: //Choose a random color, set all components to that color
			System.out.println("Monocolor");
			c = possibleColors[r.nextInt(possibleColors.length)];
			for(PuzzleComponent p : components)
			{
				p.setColor(c);
			}
			break;
		case Constants.COLORING_RANDOM:	//Choose a random color for all components
			System.out.println("Random");
			for(PuzzleComponent p : components)
			{
				c = possibleColors[r.nextInt(possibleColors.length)];
				System.out.println("Setting component to " + c);
				p.setColor(c);
			}
			break;
		case Constants.COLORING_ROTATE:	//Color in the components in the order given
			System.out.println("Rotate");
			for(int i = 0; i < components.size(); i++)
			{
				PuzzleComponent p = components.get(i);
				c = possibleColors[i % possibleColors.length];
				p.setColor(c);
			}
			break;
		default:
			break;
		}
		
	}
}
